package com.yunkeji.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;

import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunkeji.common.constant.CacheConstants;
import com.yunkeji.common.core.domain.PageQuery;
import com.yunkeji.common.core.page.TableDataInfo;
import com.yunkeji.common.enums.app.CheckStatus;
import com.yunkeji.common.enums.app.CheckType;
import com.yunkeji.common.enums.app.EnableEnum;
import com.yunkeji.common.enums.app.SexEnum;
import com.yunkeji.common.exception.ServiceException;
import com.yunkeji.common.msg.PushMessage;
import com.yunkeji.dao.domain.*;
import com.yunkeji.dao.mapper.*;
import com.yunkeji.dao.vo.UserCheckVo;
import com.yunkeji.oss.core.OssClient;
import com.yunkeji.oss.factory.OssFactory;
import com.yunkeji.system.domain.bo.CheckBo;
import com.yunkeji.system.service.ISysConfigService;
import com.yunkeji.system.service.IUserCheckService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * 用户信息审核Service业务层处理
 *
 * @author zhang
 * @date 2024-07-10
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class UserCheckServiceImpl implements IUserCheckService {

    private final UserCheckMapper baseMapper;
    private final AppUserMapper appUserMapper;
    private final AppUserExtMapper appUserExtMapper;
    private final AppUserVipMapper appUserVipMapper;
    private final ISysConfigService configService;
    private final AppUserAlbumMapper albumMapper;

    /**
     * 查询用户信息审核
     */
    @Override
    public UserCheckVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询用户信息审核列表
     */
    @Override
    public TableDataInfo<UserCheckVo> queryPageList(CheckBo bo, PageQuery pageQuery) {
//        LambdaQueryWrapper<UserCheck> lqw = buildQueryWrapper(bo);
//        Page<UserCheckVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        Page<UserCheckVo> result = baseMapper.selectListPage(
            bo.getPlatformId(),
            bo.getCheckType(),
            bo.getStatus(),
            pageQuery.build());
        List<UserCheckVo> list = result.getRecords();
        list.forEach(item -> {
            if (item.getCheckType().equals(CheckType.实名认证.getCode())) {
                CheckType.RealAuth realauth = JSONUtil.toBean(item.getCheckRes(), CheckType.RealAuth.class);
                String start = realauth.getCardNum().substring(0, 6);
                String end = realauth.getCardNum().substring(14);
                realauth.setCardNum(start + "******" + end);
                item.setCheckRes(realauth.toString());
            }
        });
        result.setRecords(list);
        return TableDataInfo.build(result);
    }

    /**
     * 查询用户信息审核列表
     */
    @Override
    public List<UserCheckVo> queryList(CheckBo bo) {
        LambdaQueryWrapper<UserCheck> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<UserCheck> buildQueryWrapper(CheckBo bo) {
        LambdaQueryWrapper<UserCheck> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getCheckType() != null, UserCheck::getCheckType, bo.getCheckType());
        lqw.eq(bo.getStatus() != null, UserCheck::getStatus, bo.getStatus());
        lqw.eq(bo.getPlatformId() != null, UserCheck::getPlatformId, bo.getPlatformId());
        lqw.orderByDesc(UserCheck::getCreateTime);
        return lqw;
    }

    /**
     * 新增用户信息审核
     */
    @Override
    public Boolean insertByBo(CheckBo bo) {
        UserCheck add = BeanUtil.toBean(bo, UserCheck.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改用户信息审核
     */
    @Override
    public Boolean updateByBo(CheckBo bo) {
        UserCheck update = BeanUtil.toBean(bo, UserCheck.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(UserCheck entity) {
        // TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除用户信息审核
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO 做一些业务上的校验,判断是否需要校验
            List<UserCheck> checks = baseMapper.selectBatchIds(ids);
            if (checks.isEmpty()) {
                return true;
            }
            List<Long> albumIds = new ArrayList<>(checks.size());
            checks.forEach(check -> {
                if (check.getStatus().equals(CheckStatus.待审核.getCode())) {
                    throw new ServiceException("未审核无法删除");
                }
                //删除审核类型为封面相册认证的审核记录时，需要把用户上传的的相册照片一起删除
                if (check.getCheckType().equals(CheckType.封面相册认证.getCode())) {
                    Long albumId = JSONUtil.toBean(check.getCheckRes(), CheckType.CoverAlbumAuth.class).getAlbumId();
                    albumIds.add(albumId);
                }
                //删除审核类型为头像认证的审核记录时，需要把用户的头像一起删除
                if (check.getCheckType().equals(CheckType.头像认证.getCode())) {
                    // 查询扩展信息
                    AppUserExt appUserExt = appUserExtMapper.selectById(check.getUserId());
                    appUserExt.setHeadUrl("");
                    appUserExtMapper.updateById(appUserExt);
                }

            });

            if (!albumIds.isEmpty()) {
                albumMapper.deleteBatchIds(albumIds);
            }

//            ids.forEach(
//                item -> {
//                    UserCheck userCheck = baseMapper.selectById(item);
//                    boolean equals = userCheck.getStatus().equals(CheckStatus.待审核.getCode());
//                    if (equals) {
//                        throw new ServiceException("未审核无法删除");
//                    }
//                });
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Lock4j(
        name = CacheConstants.LOCK_CHECK_LOCK,
        keys = {"#bo.id"})
    public void refuse(CheckBo bo) {
        UserCheck userCheck = baseMapper.selectById(bo.getId());
        if (!userCheck.getStatus().equals(CheckStatus.待审核.getCode())) {
            throw new ServiceException("操作失败");
        }
        userCheck.setRemark(bo.getReason());
        userCheck.setStatus(CheckStatus.审核拒绝.getCode());
        baseMapper.updateById(userCheck);

        AppUser appUser = appUserMapper.selectById(userCheck.getUserId());
        CheckType byCode = CheckType.getByCode(userCheck.getCheckType());
        List<String> res = null;
        switch (byCode) {
            case 真人认证:
                res = JSONUtil.toBean(userCheck.getCheckRes(), CheckType.VideoAuth.class).getRes();
                break;
            case 头像认证:
                res = JSONUtil.toBean(userCheck.getCheckRes(), CheckType.HeadAuth.class).getRes();
                break;
            case 视频介绍认证:
                res = JSONUtil.toBean(userCheck.getCheckRes(), CheckType.CoverVideoAuth.class).getRes();
                break;
            case 封面相册认证:
                // 相册有单独的管理
                CheckType.CoverAlbumAuth coveralbumauth =
                    JSONUtil.toBean(userCheck.getCheckRes(), CheckType.CoverAlbumAuth.class);
                Long albumId = coveralbumauth.getAlbumId();
                AppUserAlbum appUserAlbum = AppUserAlbum.builder().build().selectById(albumId);
                if (appUserAlbum == null) {
                    // 设置之后用户把照片删除了,审核记录还在
                    throw new ServiceException("用户已取消设置该相册");
                }
                appUserAlbum.setStatus(CheckStatus.审核拒绝.getCode());
                appUserAlbum.updateById();
                res = ListUtil.of(appUserAlbum.getResUrl());
                break;
            case 语音介绍认证:
                res = JSONUtil.toBean(userCheck.getCheckRes(), CheckType.VoiceAuth.class).getRes();
                break;
            default:
                break;
        }
        if (CollectionUtil.isNotEmpty(res)) {
            res.forEach(
                item -> {
                    OssClient storage = OssFactory.instance();
                    storage.delete(item);
                });
        }
        PushMessage.sendSysNotify(
            appUser.getPlatformId(), "您的" + byCode.name() + "审核被拒绝,拒绝原因:" + bo.getReason());
    }

    @Override
    @Lock4j(
        name = CacheConstants.LOCK_CHECK_LOCK,
        keys = {"#bo.id"})
    public void pass(CheckBo bo) {

        UserCheck userCheck = baseMapper.selectById(bo.getId());
        if (!userCheck.getStatus().equals(CheckStatus.待审核.getCode())) {
            throw new ServiceException("操作失败");
        }
        userCheck.setRemark(bo.getReason());
        userCheck.setStatus(CheckStatus.审核通过.getCode());
        baseMapper.updateById(userCheck);

        CheckType byCode = CheckType.getByCode(userCheck.getCheckType());
        AppUser appUser = appUserMapper.selectById(userCheck.getUserId());
        // AppUserExt appUserExt = appUserExtMapper.selectById(userCheck.getUserId());

        AppUserExt newExt = new AppUserExt();
        newExt.setId(userCheck.getUserId());

        AppUser newUser = new AppUser();
        newUser.setId(userCheck.getUserId());

        switch (byCode) {
            case 真人认证:
                CheckType.VideoAuth videoauth =
                    JSONUtil.toBean(userCheck.getCheckRes(), CheckType.VideoAuth.class);
                newUser.setVideoAuth(CheckStatus.审核通过.getCode());
                newUser.setLevel(1);
                // #228  通话价格-用户通过真人认证后，视频价格自动调整为20金币
                newUser.setVideoPrice(new BigDecimal(20));
                newExt.setVideoAuthUrl(videoauth.getResUrl());
                appUserMapper.updateById(newUser);
                appUserExtMapper.updateById(newExt);

                // @老张 女性真人认证通过了就送60天提现专属会员。
                Integer sex = appUser.getSex();
                Date beforeTime = null;
                if (sex.equals(SexEnum.女.getCode())) {
                    AppUserVip appUserVip = appUserVipMapper.selectById(appUser.getId());

                    AppUserVip newVip = AppUserVip.builder().id(appUserVip.getId()).build();
                    Integer exclusiveVipFlag = appUserVip.getExclusiveVipFlag();

                    if (EnableEnum.YES.getCode().equals(exclusiveVipFlag)) {
                        // 之前是vip
                        Date vipExpireTime = appUserVip.getExclusiveVipExpireTime();
                        DateTime dateTime = DateUtil.offsetDay(vipExpireTime, 60);
                        newVip.setExclusiveVipExpireTime(dateTime);
                    } else {
                        DateTime dateTime = DateUtil.offsetDay(new Date(), 60);
                        newVip.setExclusiveVipExpireTime(dateTime);
                    }
                    log.info("@老张 女性真人认证通过了就送60天提现专属会员。");
                    newVip.setExclusiveVipFlag(EnableEnum.YES.getCode());
                    appUserVipMapper.updateById(newVip);
                }

                break;
            case 实名认证:
                newUser.setCardAuth(CheckStatus.审核通过.getCode());
                CheckType.RealAuth realauth =
                    JSONUtil.toBean(userCheck.getCheckRes(), CheckType.RealAuth.class);
                newExt.setRealName(realauth.getRealName());
                newExt.setCardNum(realauth.getCardNum());
                newExt.setCardAuthUrl(realauth.getResUrl());
                appUserExtMapper.updateById(newExt);
                break;
            case 头像认证:
                CheckType.HeadAuth headauth =
                    JSONUtil.toBean(userCheck.getCheckRes(), CheckType.HeadAuth.class);
                newExt.setHeadUrl(headauth.getHeadUrl());
                appUserExtMapper.updateById(newExt);
                break;
            case 视频介绍认证:
                CheckType.CoverVideoAuth covervideoauth =
                    JSONUtil.toBean(userCheck.getCheckRes(), CheckType.CoverVideoAuth.class);
                newExt.setVideoIntro(covervideoauth.getVideoIntro());
                newExt.setVideoIntroCover(covervideoauth.getVideoIntroCover());
                newExt.setVideoIntroCoverGif(covervideoauth.getVideoIntroCoverGif());
                appUserExtMapper.updateById(newExt);
                break;
            case 封面相册认证:
                CheckType.CoverAlbumAuth coveralbumauth =
                    JSONUtil.toBean(userCheck.getCheckRes(), CheckType.CoverAlbumAuth.class);
                Long albumId = coveralbumauth.getAlbumId();

                AppUserAlbum appUserAlbum = AppUserAlbum.builder().build().selectById(albumId);
                if (appUserAlbum != null) {
                    appUserAlbum.setStatus(CheckStatus.审核通过.getCode());
                    appUserAlbum.updateById();
                }
                //   appUserExtMapper.updateById(newExt);
                break;
            case 语音介绍认证:
                CheckType.VoiceAuth voiceauth =
                    JSONUtil.toBean(userCheck.getCheckRes(), CheckType.VoiceAuth.class);
                newExt.setVoiceIntro(voiceauth.getVoiceUrl());
                appUserExtMapper.updateById(newExt);
                break;
            case 昵称认证:
                CheckType.NickNameAuth nicknameauth =
                    JSONUtil.toBean(userCheck.getCheckRes(), CheckType.NickNameAuth.class);
                newExt.setNickName(nicknameauth.getNickName());
                appUserExtMapper.updateById(newExt);
                break;
        }

        PushMessage.sendSysNotify(
            appUser.getPlatformId(), "您的" + byCode.name() + "审核已经通过，请前往个人中心查看");
    }

    @Override
    public void cancelRealAuth(CheckBo bo) {
        AppUser appUser = appUserMapper.selectById(bo.getId());
        if (Objects.isNull(appUser)) {
            throw new ServiceException("该用户不存在！");
        }
        if (!appUser.getVideoAuth().equals(CheckStatus.审核通过.getCode())) {
            throw new ServiceException("操作失败，只能对已经通过真人认证的用户进行该操作。");
        }
        UserCheck userCheck = baseMapper.selectOne(
            Wrappers.lambdaQuery(UserCheck.class)
                .eq(UserCheck::getUserId, bo.getId())
                .eq(UserCheck::getStatus, CheckStatus.审核通过.getCode())
                .eq(UserCheck::getCheckType, CheckType.真人认证.getCode()));
        if (Objects.isNull(userCheck)) {
            throw new ServiceException("操作失败，只能对已经通过真人认证的用户进行该操作。");
        }
        Date passTime = userCheck.getUpdateTime();
        userCheck.setRemark(bo.getReason());
        userCheck.setStatus(CheckStatus.审核拒绝.getCode());
        baseMapper.updateById(userCheck);

        appUser.setVideoAuth(CheckStatus.审核拒绝.getCode());
        // 通话价格-用户真人认证被取消后，视频价格自动调整为8金币
        appUser.setVideoPrice(new BigDecimal(8));
        appUserMapper.updateById(appUser);

        // 如果是女性真人认证被取消，则判断真人认证通过的时间与当前时间是否超过了60天，没超过则扣除剩余的会员时间。
        if (appUser.getSex().equals(SexEnum.女.getCode())) {
            long days = DateUtil.between(passTime, new Date(), DateUnit.DAY);
            if (days > 60) {
                return;
            }
            AppUserVip appUserVip = appUserVipMapper.selectById(appUser.getId());
            Date vipExpireTime = appUserVip.getExclusiveVipExpireTime();
            DateTime dateTime = DateUtil.offsetDay(vipExpireTime, (int) (days - 60));
            log.info("如果是女性真人认证被取消，则判断真人认证通过的时间与当前时间是否超过了60天，没超过则扣除剩余的会员时间。");
            appUserVip.setExclusiveVipExpireTime(dateTime);
            //判断扣除后的时间是否小于当前时间，如果小于则更改用户的VIP标识
            if (dateTime.getTime() <= System.currentTimeMillis()) {
                appUserVip.setExclusiveVipFlag(EnableEnum.NO.getCode());
            }
            appUserVipMapper.updateById(appUserVip);
        }
    }

    @Override
    public void setFaceScore(CheckBo bo) {
        AppUser appUser = appUserMapper.selectById(bo.getId());
        if (Objects.isNull(appUser)) {
            throw new ServiceException("该用户不存在！");
        }
        if (!appUser.getVideoAuth().equals(CheckStatus.审核通过.getCode())) {
            throw new ServiceException("操作失败，只能对已经通过真人认证的用户进行该操作。");
        }
        int sort;
        switch (bo.getFaceScore()) {
            case 1:
                sort = 1000;
                break;
            case 2:
                sort = 2000;
                break;
            default:
                sort = 0;
        }
        appUser.setSort(sort);
        appUserMapper.updateById(appUser);
    }
}
